﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Data.SqlClient;

namespace KnowledgeEntity
{
   public class Category: IEnumerable
   {
      public int ID { get; private set; }
      public string Name { get; private set; }

      public Category(int id, string name)
      {
         ID = id;
         Name = name;
      }

      private Dictionary<string, Category> _list = new Dictionary<string, Category>();

      public IEnumerator GetEnumerator()
      {
         foreach (KeyValuePair<string, Category> childKeyValue in _list)
            yield return childKeyValue.Value;
      }

      public bool IsChildExists(Category category)
      {
         return _list.ContainsKey(category.Name);
      }

      public int ChildrenCount { get { return _list.Count; } }

      /// <summary>
      /// 保证子对象只会被加入一次
      /// 递归判断以确保目标分类对象不存在于子对象的子树中
      /// </summary>
      /// <param name="child"></param>
      public void AddChild(Category child)
      {
         if (_list.Count <= 0)
         {
            _list.Add(child.Name,child);
            return;
         }
         if (_list.ContainsKey(child.Name))
            throw new CategoryExistException(child);

         if (child._list.Count <= 0)
         {
            _list.Add(child.Name, child);
            return;
         }
         //如果当前分类已存在于child的子分类中
         //则抛出异常
         if (IsChild(child, this))
            throw new CategoryAddingOverFlowException(child);

         _list.Add(child.Name, child);
      }

      /// <summary>
      /// 判断target是否存在于root的子树中
      /// </summary>
      /// <param name="root"></param>
      /// <param name="target"></param>
      /// <returns></returns>
      private bool IsChild(Category root, Category target)
      {
         //如果参数为空引用，则抛出异常
         if (root == null) throw new ArgumentNullException("root");
         if (target == null) throw new ArgumentNullException("target");
         //

         //如果root已为叶节点，则target不是root的子项
         if (root.ChildrenCount <= 0) return false;
         //

         //如果root的子项中包括target，则返回true
         if (root.IsChildExists(target)) return true;
         //

         //递归判断target是否是root的各个子项的子项
         foreach (Category category in root)
         {
            if (IsChild(category, target)) return true;
         }
         //

         return false;
      }

      /// <summary>
      /// 从数据库读取所有的分类
      /// </summary>
      /// <returns></returns>
      public static Dictionary<int, Category> GetAllCategories()
      {
         Dictionary<int, Category> list = new Dictionary<int, Category>();
         list.Add(-1, new Category(-1, string.Empty));

         string query = @"select ID, Name, Description, ParentID from Category";

         using (SqlDataReader categoryReader = DBHelper.SqlHelper.GetReader(query))
         {
            while (categoryReader.Read())
            {
               Category item = new Category(categoryReader.GetInt32(0), categoryReader.GetString(1));
               int parentID = categoryReader.GetInt32(3);
               if (list.ContainsKey(parentID))
                  list[parentID].AddChild(item);

               list.Add(item.ID, item);
            }

            return list;
         }
      }

      /// <summary>
      /// 测试方法，生成测试用字典对象
      /// </summary>
      /// <returns></returns>
      public static Dictionary<int, Category> GetTestCategory()
      {
         Dictionary<int, Category> list = new Dictionary<int, Category>();

         Category level_0 = new Category(1, "计算机科学与技术");
         Category level_0_0 = new Category(2, "硬件工程");
         Category level_0_1 = new Category(3, "软件工程");
         Category level_0_1_0 = new Category(4, "系统分析与设计");
         Category level_0_1_1 = new Category(5, "测试技术");
         Category level_0_1_2 = new Category(6, "开发技术");
         Category level_0_1_2_0 = new Category(7, "Web开发");
         Category level_0_1_2_1 = new Category(8, "移动应用开发");
         Category level_0_1_2_2 = new Category(9, "桌面应用开发");

         level_0_1_2.AddChild(level_0_1_2_0);
         level_0_1_2.AddChild(level_0_1_2_1);
         level_0_1_2.AddChild(level_0_1_2_2);

         level_0_1.AddChild(level_0_1_0);
         level_0_1.AddChild(level_0_1_1);
         level_0_1.AddChild(level_0_1_2);

         level_0.AddChild(level_0_0);
         level_0.AddChild(level_0_1);

         list.Add(level_0.ID, level_0);
         list.Add(level_0_0.ID, level_0_0);
         list.Add(level_0_1.ID, level_0_1);
         list.Add(level_0_1_0.ID, level_0_1_0);
         list.Add(level_0_1_1.ID, level_0_1_1);
         list.Add(level_0_1_2.ID, level_0_1_2);
         list.Add(level_0_1_2_0.ID, level_0_1_2_0);
         list.Add(level_0_1_2_1.ID, level_0_1_2_1);
         list.Add(level_0_1_2_2.ID, level_0_1_2_2);

         return list;
      }
   }
}
